#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
割叶机PLC控制系统 - Flask服务器
支持WASD控制和PLC数据读取
"""

import logging
import socket
import threading
import json
from flask import Flask, render_template, request, jsonify
from flask_socketio import SocketIO, emit

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    handlers=[
        logging.StreamHandler(),
        logging.FileHandler('plc_control.log', encoding='utf-8')
    ]
)
logger = logging.getLogger(__name__)

app = Flask(__name__)
app.config['SECRET_KEY'] = 'plc_control_secret_key'
socketio = SocketIO(app, cors_allowed_origins="*", logger=True, engineio_logger=True)

# 全局变量
rk3588_client = None
rk3588_lock = threading.Lock()
system_status = {
    'rk3588_connected': False,
    'plc_connected': False,
    'control_mode': 0,
    'movement': {'forward': 0, 'turn': 0},
    'sensors': {
        'generator_voltage': 0,
        'generator_current': 0,
        'generator_power': 0,
        'generator_temp': 0,
        'engine_temp': 0,
        'hot_water_temp': 0,
        'cooling_temp': 0,
        'box_temp': 0,
        'fuel_level': 0,
        'water_level': 0,
        'plc_output_status': 0
    },
    'controls': {
        'generator_control': 0,
        'relay_220v': 0,
        'water_spray': 0,
        'cooling_control': 0,
        'speed_percent': 0,
        'leaf_cutter': 0
    }
}

class TCPServer:
    """TCP服务器，接收RK3588连接"""
    
    def __init__(self, host='0.0.0.0', port=9000):
        self.host = host
        self.port = port
        self.server_socket = None
        self.running = False
        
    def start(self):
        """启动TCP服务器"""
        try:
            self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.server_socket.bind((self.host, self.port))
            self.server_socket.listen(5)
            self.running = True
            
            logger.info(f"TCP服务器启动: {self.host}:{self.port}")
            logger.info(f"✅ TCP服务器正在监听端口{self.port}，等待RK3588连接...")
            
            while self.running:
                try:
                    client_socket, client_address = self.server_socket.accept()
                    logger.info(f"🎉 RK3588连接成功: {client_address}")
                    
                    client_thread = threading.Thread(
                        target=self.handle_client,
                        args=(client_socket, client_address),
                        daemon=True
                    )
                    client_thread.start()
                    logger.info(f"✅ 客户端处理线程已启动: {client_address}")
                    
                except Exception as e:
                    if self.running:
                        logger.error(f"❌ 接受连接失败: {e}")
                        
        except Exception as e:
            logger.error(f"TCP服务器启动失败: {e}")
            
    def handle_client(self, client_socket, client_address):
        """处理RK3588客户端"""
        global rk3588_client, system_status
        
        try:
            with rk3588_lock:
                rk3588_client = client_socket
                system_status['rk3588_connected'] = True
                
            socketio.emit('status_update', system_status)
            
            while self.running:
                try:
                    data = client_socket.recv(1024)
                    if not data:
                        break
                        
                    message = data.decode('utf-8').strip()
                    if not message:
                        continue
                    
                    lines = message.split('\n')
                    for line in lines:
                        line = line.strip()
                        if line and line.startswith('{'):
                            try:
                                logger.info(f"收到RK3588数据: {line}")
                                data_dict = json.loads(line)
                                self.process_rk3588_data(data_dict)
                            except json.JSONDecodeError as je:
                                logger.error(f"JSON解析失败: {je}")
                        
                except socket.timeout:
                    continue
                except Exception as e:
                    logger.error(f"接收数据失败: {e}")
                    break
                    
        except Exception as e:
            logger.error(f"客户端处理失败: {e}")
        finally:
            with rk3588_lock:
                if rk3588_client == client_socket:
                    rk3588_client = None
                    system_status['rk3588_connected'] = False
                    
            client_socket.close()
            logger.info(f"👋 RK3588断开: {client_address}")
            socketio.emit('status_update', system_status)
            
    def process_rk3588_data(self, data):
        """处理RK3588发送的数据"""
        global system_status
        
        try:
            data_type = data.get('type')
            
            if data_type == 'status':
                if 'plc_connected' in data:
                    system_status['plc_connected'] = data['plc_connected']
                socketio.emit('status_update', system_status)
                
            elif data_type == 'sensor_data':
                if 'sensors' in data:
                    system_status['sensors'].update(data['sensors'])
                socketio.emit('sensor_response', {
                    'success': True,
                    'sensors': system_status['sensors']
                })
                
            elif data_type == 'movement_response':
                socketio.emit('movement_response', {
                    'success': data.get('success', False),
                    'forward': data.get('forward', 0),
                    'turn': data.get('turn', 0)
                })
            
            elif data_type == 'usb_check_result':
                socketio.emit('usb_check_result', data)
                logger.info(f"USB检测结果: {data.get('result')}")
            
            elif data_type == 'plc_connect_result':
                socketio.emit('plc_connect_result', data)
                logger.info(f"PLC连接结果: {data.get('result')}")
                
                if data.get('result', {}).get('success'):
                    system_status['plc_connected'] = True
                    socketio.emit('status_update', system_status)
            
            elif data_type == 'control_response':
                socketio.emit('control_response', {
                    'success': data.get('success', False),
                    'type': data.get('control_type'),
                    'value': data.get('value', 0)
                })
                logger.info(f"控制响应: {data.get('control_type')}={data.get('value')}")
                    
        except Exception as e:
            logger.error(f"处理RK3588数据失败: {e}")
            
    def send_command(self, command):
        """发送命令到RK3588"""
        global rk3588_client
        
        try:
            with rk3588_lock:
                if rk3588_client:
                    message = json.dumps(command) + '\n'
                    rk3588_client.send(message.encode('utf-8'))
                    logger.info(f"发送命令到RK3588: {command}")
                    return True
                else:
                    logger.warning("RK3588未连接")
                    return False
        except Exception as e:
            logger.error(f"发送命令失败: {e}")
            return False
            
    def stop(self):
        """停止TCP服务器"""
        self.running = False
        if self.server_socket:
            self.server_socket.close()

tcp_server = TCPServer()

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/api/status')
def get_status():
    return jsonify(system_status)

@socketio.on('connect')
def handle_connect(auth):
    logger.info(f"Web客户端连接: {request.sid}")
    emit('status_update', system_status)

@socketio.on('disconnect')
def handle_disconnect():
    logger.info(f"Web客户端断开: {request.sid}")

@socketio.on('movement_control')
def handle_movement_control(data):
    try:
        forward = data.get('forward', 0)
        turn = data.get('turn', 0)
        
        forward = max(-25, min(25, forward))
        turn = max(-12, min(12, turn))
        
        system_status['movement']['forward'] = forward
        system_status['movement']['turn'] = turn
        
        command = {
            'type': 'movement',
            'forward': forward,
            'turn': turn
        }
        
        success = tcp_server.send_command(command)
        
        emit('movement_response', {
            'success': success,
            'forward': forward,
            'turn': turn
        })
        
        logger.info(f"移动控制: 前进={forward}, 转向={turn}")
        
    except Exception as e:
        logger.error(f"移动控制失败: {e}")
        emit('movement_response', {'success': False, 'error': str(e)})

@socketio.on('control_command')
def handle_control_command(data):
    try:
        control_type = data.get('type')
        value = data.get('value', 0)
        
        command = {
            'type': 'control',
            'control_type': control_type,
            'value': value
        }
        
        success = tcp_server.send_command(command)
        
        if success and control_type in system_status['controls']:
            system_status['controls'][control_type] = value
            
        emit('control_response', {
            'success': success,
            'type': control_type,
            'value': value
        })
        
        logger.info(f"控制命令: {control_type}={value}")
        
    except Exception as e:
        logger.error(f"控制命令失败: {e}")
        emit('control_response', {'success': False, 'error': str(e)})

@socketio.on('check_usb')
def handle_check_usb():
    try:
        command = {'type': 'check_usb'}
        success = tcp_server.send_command(command)
        
        if not success:
            emit('usb_check_result', {
                'result': {
                    'success': False,
                    'message': 'RK3588未连接'
                }
            })
        
    except Exception as e:
        logger.error(f"检测USB失败: {e}")
        emit('usb_check_result', {
            'result': {
                'success': False,
                'message': str(e)
            }
        })

@socketio.on('connect_plc')
def handle_connect_plc():
    try:
        command = {'type': 'connect_plc'}
        success = tcp_server.send_command(command)
        
        if not success:
            emit('plc_connect_result', {
                'result': {
                    'success': False,
                    'message': 'RK3588未连接'
                }
            })
        
    except Exception as e:
        logger.error(f"连接PLC失败: {e}")
        emit('plc_connect_result', {
            'result': {
                'success': False,
                'message': str(e)
            }
        })

@socketio.on('request_sensor_data')
def handle_request_sensor_data():
    try:
        command = {'type': 'read_sensors'}
        success = tcp_server.send_command(command)
        
        if not success:
            emit('sensor_response', {
                'success': False,
                'error': 'RK3588未连接'
            })
                
    except Exception as e:
        logger.error(f"请求传感器数据失败: {e}")
        emit('sensor_response', {'success': False, 'error': str(e)})

@socketio.on('continuous_forward_test')
def handle_continuous_forward_test(data):
    try:
        duration = data.get('duration', 5000)
        
        command = {
            'type': 'continuous_forward',
            'duration': duration
        }
        
        success = tcp_server.send_command(command)
        
        if not success:
            emit('control_response', {
                'success': False,
                'error': 'RK3588未连接'
            })
        else:
            logger.info(f"持续前进测试: {duration}ms")
        
    except Exception as e:
        logger.error(f"持续前进测试失败: {e}")
        emit('control_response', {'success': False, 'error': str(e)})

def start_tcp_server():
    tcp_thread = threading.Thread(target=tcp_server.start, daemon=True)
    tcp_thread.start()

if __name__ == '__main__':
    try:
        start_tcp_server()
        logger.info("启动Flask服务器...")
        socketio.run(app, host='0.0.0.0', port=5000, debug=False)
        
    except KeyboardInterrupt:
        logger.info("收到中断信号，正在关闭...")
    except Exception as e:
        logger.error(f"服务器启动失败: {e}")
    finally:
        tcp_server.stop()
        logger.info("服务器已关闭")

